package com.linkhub.oms.admin.modules.user.accountflow.service.impl;

import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.common.exception.OrderExceptionFactory;
import com.linkhub.oms.admin.modules.order.service.OrderInfoAssembleService;
import com.linkhub.oms.admin.modules.product.service.LocalProductCalculateService;
import com.linkhub.oms.admin.modules.user.accountflow.domain.vo.FreightAccountFlowDetailVO;
import com.linkhub.oms.admin.modules.user.accountflow.domain.vo.PickUpAccountFlowDetailVO;
import com.linkhub.oms.admin.modules.user.accountflow.domain.vo.ProcessingAccountFlowDetailVo;
import com.linkhub.oms.admin.modules.user.accountflow.domain.vo.ProductListVo;
import com.linkhub.oms.admin.modules.user.accountflow.service.IUserAccountFlowBizService;
import com.linkhub.oms.admin.modules.user.accountflow.service.IUserAccountFlowDetailService;
import com.linkhub.oms.common.enums.mp.DocumentTypeEnum;
import com.linkhub.oms.common.enums.mp.ExpenseTypeEnum;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.dao.mpservice.IEntryOrderLineService;
import com.linkhub.oms.dao.mpservice.ILocalProductService;
import com.linkhub.oms.dao.mpservice.IPickUpGoodsOrderService;
import com.linkhub.oms.dao.mpservice.IProcessOrderRecordService;
import com.linkhub.oms.dao.mpservice.IUserAccountFlowService;
import com.linkhub.oms.entity.EntryOrderLineEntity;
import com.linkhub.oms.entity.LocalProductEntity;
import com.linkhub.oms.entity.PickUpGoodsOrderEntity;
import com.linkhub.oms.entity.ProcessOrderRecordEntity;
import com.linkhub.oms.entity.UserAccountFlowEntity;
import com.linkhub.oms.entity.resulttype.order.OrderInfoDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author Redball
 * @version 1.0.0
 * @Description UserAccountFlowDetailServiceImpl
 * @createTime 2024/7/31 下午12:42
 */
@Service
@Slf4j
public class UserAccountFlowDetailServiceImpl implements IUserAccountFlowDetailService {

    @Resource
    private IUserAccountFlowService userAccountFlowService;

    @Resource
    private IUserAccountFlowBizService userAccountFlowBizService;

    @Resource
    private OrderInfoAssembleService orderInfoAssembleService;

    @Resource
    private LocalProductCalculateService localProductCalculateService;

    @Resource
    private ILocalProductService localProductService;

    @Resource
    private IProcessOrderRecordService processOrderRecordService;

    @Resource
    private IPickUpGoodsOrderService pickUpGoodsOrderService;

    @Resource
    private IEntryOrderLineService entryOrderLineService;

    @Override
    public FreightAccountFlowDetailVO queryFreightAccountFlowDetail(String transactionId) {
        UserAccountFlowEntity userAccountFlow = getAndCheckUserAccountFlowByTransactionId(transactionId, DocumentTypeEnum.ORDER);

        List<UserAccountFlowEntity> accountFlows = userAccountFlowBizService.queryAccountFlow(
                userAccountFlow.getDocumentId(),
                userAccountFlow.getTransactionType(),
                userAccountFlow.getDocumentType()
        );
        Map<ExpenseTypeEnum, BigDecimal> expenseMap = QtStreamUtil.toMap(accountFlows, UserAccountFlowEntity::getExpenseType, UserAccountFlowEntity::getAmount);

        String sysOrderId = userAccountFlow.getDocumentId();
        OrderInfoDO orderInfoDO = orderInfoAssembleService.assembleOrder(sysOrderId);
        if(orderInfoDO==null || orderInfoDO.getOrder() == null){
            throw OrderExceptionFactory.getInvalidOrderId();
        }
        List<ProductListVo> productListVos = QtStreamUtil.map(orderInfoDO.getOrderLocalProducts(), ProductListVo::new);
        productListVos.addAll(QtStreamUtil.map(orderInfoDO.getOrderShopProducts(), ProductListVo::new));

        FreightAccountFlowDetailVO detailVO = new FreightAccountFlowDetailVO();
        detailVO.setSysOrderId(sysOrderId);
        detailVO.setFreight(expenseMap.getOrDefault(ExpenseTypeEnum.FREIGHT, BigDecimal.ZERO));
        detailVO.setRegistrationFee(expenseMap.getOrDefault(ExpenseTypeEnum.REGISTRATION_FEE, BigDecimal.ZERO));
        detailVO.setOperatingCharge(expenseMap.getOrDefault(ExpenseTypeEnum.OPERATE, BigDecimal.ZERO));
        detailVO.setVat(expenseMap.getOrDefault(ExpenseTypeEnum.VAT, BigDecimal.ZERO));
        detailVO.setHandlingFee(expenseMap.getOrDefault(ExpenseTypeEnum.VAT_HANDLING_FEE, BigDecimal.ZERO));
        detailVO.setPackageWeight(localProductCalculateService.getOrderProductWeightTotal(sysOrderId));
        detailVO.setProducts(productListVos);
        return detailVO;
    }

    @Override
    public ProcessingAccountFlowDetailVo queryProcessingAccountFlowDetail(String transactionId) {
        UserAccountFlowEntity userAccountFlow = getAndCheckUserAccountFlowByTransactionId(transactionId, DocumentTypeEnum.PROCESS_ORDER);

        String processOrderCode = userAccountFlow.getDocumentId();
        ProcessOrderRecordEntity processOrderRecord = processOrderRecordService.getProcessOrderRecordByOrderCode(processOrderCode);
        if (Objects.isNull(processOrderRecord)) {
            throw ExceptionFactory.getI18nBizException("process.order.sysProcessOrderCode.error");
        }
        LocalProductEntity localProduct = localProductService.getBySkuId(processOrderRecord.getSkuId());
        if (Objects.isNull(localProduct)) {
            throw ExceptionFactory.getI18nBizException("local.product.not.exist");
        }

        ProcessingAccountFlowDetailVo detailVO = new ProcessingAccountFlowDetailVo();
        detailVO.setProcessOrderCode(processOrderCode);
        detailVO.setProcessingFee(userAccountFlow.getAmount());
        detailVO.setCombinedProduct(new ProductListVo(localProduct, processOrderRecord.getSkuQuantity()));

        return detailVO;
    }

    @Override
    public PickUpAccountFlowDetailVO queryPickUpAccountFlowDetail(String transactionId) {
        UserAccountFlowEntity userAccountFlow = getAndCheckUserAccountFlowByTransactionId(transactionId, DocumentTypeEnum.PICK_UP_ORDER);

        String sysEntryOrderCode = userAccountFlow.getDocumentId();
        PickUpGoodsOrderEntity pickUpGoodsOrder = pickUpGoodsOrderService.queryBySysEntryOrderCode(sysEntryOrderCode);
        if (Objects.isNull(pickUpGoodsOrder)) {
            throw ExceptionFactory.getI18nBizException("pick.up.order.sysEntryOrderCode.error");
        }

        List<EntryOrderLineEntity> orderLineEntities = entryOrderLineService.listEntryOrderLines(sysEntryOrderCode);
        List<String> skuIds = QtStreamUtil.map(orderLineEntities, EntryOrderLineEntity::getSkuId);
        Map<String, LocalProductEntity> localProductMap = QtStreamUtil.toMap(localProductService.listBySkuIds(skuIds), LocalProductEntity::getSkuId);
        orderLineEntities.forEach(orderLine -> {
            LocalProductEntity localProduct = localProductMap.get(orderLine.getSkuId());
            orderLine.setSku(localProduct.getSku());
            orderLine.setProductEnTitle(localProduct.getProductEnTitle());
        });

        List<ProductListVo> productListVos = QtStreamUtil.map(orderLineEntities, ProductListVo::new);

        PickUpAccountFlowDetailVO detailVO = new PickUpAccountFlowDetailVO();
        detailVO.setSysEntryOrderCode(sysEntryOrderCode);
        detailVO.setPickUpFee(userAccountFlow.getAmount());
        detailVO.setPickUpApplyTime(pickUpGoodsOrder.getCreatedTime());
        detailVO.setProducts(productListVos);

        return detailVO;
    }

    private UserAccountFlowEntity getAndCheckUserAccountFlowByTransactionId(String transactionId, DocumentTypeEnum documentTypeEnum) {
        UserAccountFlowEntity userAccountFlow = userAccountFlowService.queryByTransactionId(transactionId);
        if (userAccountFlow == null) {
            throw ExceptionFactory.getI18nBizException("user.account.flow.transactionId.error");
        }

        if(!documentTypeEnum.equals(userAccountFlow.getDocumentType())){
            throw ExceptionFactory.getI18nBizException("user.account.flow.documentType.only.support", documentTypeEnum.getDesc());
        }

        /* if(TransactionTypeEnum.PAY.equals(userAccountFlow.getTransactionType())){

        }*/
        return userAccountFlow;
    }
}
